import java.io.File;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.util.*;
public class db_database {
	public db_lock oLock = new db_lock();
	public db_lock oDBInfoLock = new db_lock();
	public ArrayList<db_table> oTables = new ArrayList<db_table>();
	public String sPath = "";
	public String sName = "";
	private db_book oBook;

	private RandomAccessFile oFile = null;
	
	db_database (String sPath) {
		
		// Load the file and create reading glass
		try {
		oFile = new RandomAccessFile(sPath, "rwd");
		} catch (Exception e) {e.printStackTrace();}
		oBook = new db_book(oFile);

		db_reading_glass oGlass = oBook.getGlass();
		
		oGlass.seekGroup(0);

		// Read db version
		oGlass.readStr(db_util.DB_BYTE_LENGTH);
		
		// Read db name
		sName = oGlass.readStr(db_util.DB_BYTE_LENGTH);
		
		oGlass.seekGroup(1);
		long lLastPosition = 0;
		
		// Read through all table definitions
		int iTableCnt = oGlass.readInt();
		
		System.out.println("Loading " + iTableCnt + " tables in " + sName);
		
		db_table oTable = null;
		for (int i = 0; i < iTableCnt; i++) {
			oTable = null;
			// Read a table group number
			int iTableGroup = oGlass.readInt();
			lLastPosition = oGlass.position();
			
			// Loop through each table
			oGlass.seekGroup(iTableGroup);
			ArrayList<db_column> oCols = new ArrayList<db_column>();
			ArrayList<db_index> oIndex = new ArrayList<db_index>();
			if (oGlass.readLong() == db_util.DB_TABLE_STATUS_NORMAL) {
				// The table has not been deleted
				
				// Read table definition
				String sTableName = oGlass.readStr(db_util.DB_BYTE_LENGTH);
				long lDataGroupPointer = oGlass.readLong();
				long lIndexGroupPointer = oGlass.readLong();
				int iColCount = oGlass.readInt();
			
				// Loop through each column definition
				for (int k = 0; k < iColCount; k++) {
					String sColumnName = oGlass.readStr(db_util.DB_BYTE_LENGTH);
					long lDataType = oGlass.readLong();
					long lDataLength = oGlass.readLong();
					boolean bNotNull = oGlass.readInt() == 1;
					boolean bPrimaryKey = oGlass.readInt() == 1;
					boolean bIdentity = oGlass.readInt() == 1;
					long lIdentitySeed = oGlass.readLong();
					long lIdentityIncrement = oGlass.readLong();
					oCols.add(new db_column(sColumnName, (int)lDataType, (int)lDataLength, bNotNull, bPrimaryKey, bIdentity, lIdentitySeed, lIdentityIncrement));

				}
				
				// Read index information
				oGlass.seekGroup(lIndexGroupPointer);
				oGlass.readInt();
				int iIndexCnt = (int) (oGlass.length()/4)-1;
				
				long lLastIndexPosition = 0;
				
				// For every index
				for (int k = 0; k < iIndexCnt; k++) {
					int iIndexGroup = oGlass.readInt();
					lLastIndexPosition = oGlass.position();
					oGlass.seekGroup(iIndexGroup);
					System.out.println("looking at index " + iIndexGroup);
					// If its not deleted
					if (oGlass.readInt() == db_util.DB_INDEX_STATUS_NORMAL) {
						// Get name
						String sIndexName = oGlass.readStr(128);
						System.out.println(sIndexName);
						int iIndexColCnt = oGlass.readInt();
						ArrayList<String> oIndexCols = new ArrayList<String>();
						ArrayList<Integer> oIndexColsSortOrder = new ArrayList<Integer>();
						// and columns
						for (int j = 0; j < iIndexColCnt; j++) {
							oIndexCols.add(oGlass.readStr(128));
							oIndexColsSortOrder.add(oGlass.readInt());
						}
						// and data index data group pointer
						int iIndexDataGroup = oGlass.readInt();
						oIndex.add(new db_index(sIndexName, oIndexCols, oIndexColsSortOrder, iIndexDataGroup));
						// add to list
					}
					oGlass.seekGroup(lDataGroupPointer);
					oGlass.seek(lLastIndexPosition);
				}
				
				oTable = new db_table(sTableName, iTableGroup, lDataGroupPointer, lIndexGroupPointer, oIndex, oCols);
			}
			
			// make sure the table wasn't deleted
			if (oTable != null)
				oTables.add(oTable);
			
			// Return to read next table group number
			oGlass.seekGroup(1);
			oGlass.seek(lLastPosition);
		}
	}
	
	
	public db_reading_glass getGlass(){
		return oBook.getGlass();
	}
	
}
